home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / tvg110.zip / B7DEMSRC.ZIP / TVDEMO.PAS < prev   
Pascal/Delphi Source File  |  1993-02-22  |  20KB  |  714 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Demo                            }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. program TVDemo;
  9.  
  10. {$X+,S-}
  11. {$M 16384,8192,655360}
  12.  
  13. { Turbo Vision demo program. This program uses many of the Turbo
  14.   Vision standard and demo units, including:
  15.  
  16.     StdDlg    - Open file browser, change directory tree.
  17.     MsgBox    - Simple dialog to display messages.
  18.     ColorSel  - Color customization.
  19.     Gadgets   - Shows system time and available heap space.
  20.     AsciiTab  - ASCII table.
  21.     Calendar  - View a month at a time
  22.     Calc      - Desktop calculator.
  23.     HelpFile  - Context sensitive help.
  24.     MouseDlg  - Mouse options dialog.
  25.     Puzzle    - Simple brain puzzle.
  26.     Editors   - Text Editor object.
  27.  
  28.   And of course this program includes many standard Turbo Vision
  29.   objects and behaviors (menubar, desktop, status line, dialog boxes,
  30.   mouse support, window resize/move/tile/cascade).
  31. }
  32.  
  33. uses
  34.   TvGraph, TVGDefs, TVGWhiz, Styx,                     { ** TVGRAPH ** }
  35.   Dos, Objects, Drivers, Memory, Views, Menus, Dialogs, StdDlg, HistList,
  36.   MsgBox, App, DemoCmds, Gadgets, Puzzle, Calendar, AsciiTab, Calc,
  37.   HelpFile, DemoHelp, ColorSel, MouseDlg, Editors;
  38.  
  39. { If you get a FILE NOT FOUND error when compiling this program
  40.   from a DOS IDE, change to the \BP\EXAMPLES\DOS\TVDEMO directory
  41.   (use File|Change dir).
  42.  
  43.   This will enable the compiler to find all of the units used by
  44.   this program.
  45. }
  46.  
  47. const
  48.   HeapSize = 48 * (1024 div 16);  { Save 48k heap for main program }
  49.  
  50.   { Desktop file signature information }
  51.   SignatureLen = 21;
  52.   DSKSignature : string[SignatureLen] = 'TV Demo Desktop File'#26;
  53.  
  54. var
  55.   ClipWindow: PEditWindow;
  56.  
  57. type
  58.  
  59.   { TTVDemo }
  60.  
  61.   PTVDemo = ^TTVDemo;
  62.   TTVDemo = object(TVGApp)                   { ** TVGRAPH ** }
  63.     Clock: PClockView;
  64.     Heap: PHeapView;
  65.     constructor Init;
  66.     procedure FileOpen(WildCard: PathStr);
  67.     function OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  68.     procedure GetEvent(var Event: TEvent); virtual;
  69.     function GetPalette: PPalette; virtual;
  70.     procedure HandleEvent(var Event: TEvent); virtual;
  71.     procedure Idle; virtual;
  72.     procedure InitMenuBar; virtual;
  73.     procedure InitStatusLine; virtual;
  74.     procedure LoadDesktop(var S: TStream);
  75.     procedure OutOfMemory; virtual;
  76.     procedure StoreDesktop(var S: TStream);
  77.   end;
  78.  
  79. { CalcHelpName }
  80.  
  81. function CalcHelpName: PathStr;
  82. var
  83.   EXEName: PathStr;
  84.   Dir: DirStr;
  85.   Name: NameStr;
  86.   Ext: ExtStr;
  87. begin
  88.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  89.   else EXEName := FSearch('TVDEMO.EXE', GetEnv('PATH'));
  90.   FSplit(EXEName, Dir, Name, Ext);
  91.   if Dir[Length(Dir)] = '\' then Dec(Dir[0]);
  92.   CalcHelpName := FSearch('DEMOHELP.HLP', Dir);
  93. end;
  94.  
  95. function CreateFindDialog: PDialog;
  96. var
  97.   D: PDialog;
  98.   Control: PView;
  99.   R: TRect;
  100. begin
  101.   R.Assign(0, 0, 38, 12);
  102.   D := New(PDialog, Init(R, 'Find'));
  103.   with D^ do
  104.   begin
  105.     Options := Options or ofCentered;
  106.  
  107.     R.Assign(3, 3, 32, 4);
  108.     Control := New(PInputLine, Init(R, 80));
  109.     Insert(Control);
  110.     R.Assign(2, 2, 15, 3);
  111.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  112.     R.Assign(32, 3, 35, 4);
  113.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  114.  
  115.     R.Assign(3, 5, 35, 7);
  116.     Insert(New(PCheckBoxes, Init(R,
  117.       NewSItem('~C~ase sensitive',
  118.       NewSItem('~W~hole words only', nil)))));
  119.  
  120.     R.Assign(14, 9, 24, 11);
  121.     Insert(New(PButton, Init(R, 'O~K~', cmOk, bfDefault)));
  122.     Inc(R.A.X, 12); Inc(R.B.X, 12);
  123.     Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  124.  
  125.     SelectNext(False);
  126.   end;
  127.   CreateFindDialog := D;
  128. end;
  129.  
  130. function CreateReplaceDialog: PDialog;
  131. var
  132.   D: PDialog;
  133.   Control: PView;
  134.   R: TRect;
  135. begin
  136.   R.Assign(0, 0, 40, 16);
  137.   D := New(PDialog, Init(R, 'Replace'));
  138.   with D^ do
  139.   begin
  140.     Options := Options or ofCentered;
  141.  
  142.     R.Assign(3, 3, 34, 4);
  143.     Control := New(PInputLine, Init(R, 80));
  144.     Insert(Control);
  145.     R.Assign(2, 2, 15, 3);
  146.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  147.     R.Assign(34, 3, 37, 4);
  148.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  149.  
  150.     R.Assign(3, 6, 34, 7);
  151.     Control := New(PInputLine, Init(R, 80));
  152.     Insert(Control);
  153.     R.Assign(2, 5, 12, 6);
  154.     Insert(New(PLabel, Init(R, '~N~ew text', Control)));
  155.     R.Assign(34, 6, 37, 7);
  156.     Insert(New(PHistory, Init(R, PInputLine(Control), 11)));
  157.  
  158.     R.Assign(3, 8, 37, 12);
  159.     Insert(New(PCheckBoxes, Init(R,
  160.       NewSItem('~C~ase sensitive',
  161.       NewSItem('~W~hole words only',
  162.       NewSItem('~P~rompt on replace',
  163.       NewSItem('~R~eplace all', nil)))))));
  164.  
  165.     R.Assign(17, 13, 27, 15);
  166.     Insert(New(PButton, Init(R, 'O~K~', cmOk, bfDefault)));
  167.     R.Assign(28, 13, 38, 15);
  168.     Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  169.  
  170.     SelectNext(False);
  171.   end;
  172.   CreateReplaceDialog := D;
  173. end;
  174.  
  175. function DoEditDialog(Dialog: Integer; Info: Pointer): Word; far;
  176. var
  177.   R: TRect;
  178.   T: TPoint;
  179. begin
  180.   case Dialog of
  181.     edOutOfMemory:
  182.       DoEditDialog := MessageBox('Not enough memory for this operation.',
  183.         nil, mfError + mfOkButton);
  184.     edReadError:
  185.       DoEditDialog := MessageBox('Error reading file %s.',
  186.         @Info, mfError + mfOkButton);
  187.     edWriteError:
  188.       DoEditDialog := MessageBox('Error writing file %s.',
  189.         @Info, mfError + mfOkButton);
  190.     edCreateError:
  191.       DoEditDialog := MessageBox('Error creating file %s.',
  192.         @Info, mfError + mfOkButton);
  193.     edSaveModify:
  194.       DoEditDialog := MessageBox('%s has been modified. Save?',
  195.         @Info, mfInformation + mfYesNoCancel);
  196.     edSaveUntitled:
  197.       DoEditDialog := MessageBox('Save untitled file?',
  198.         nil, mfInformation + mfYesNoCancel);
  199.     edSaveAs:
  200.       DoEditDialog := Application^.ExecuteDialog(New(PFileDialog, Init('*.*',
  201.         'Save file as', '~N~ame', fdOkButton, 101)), Info);
  202.     edFind:
  203.       DoEditDialog := Application^.ExecuteDialog(CreateFindDialog, Info);
  204.     edSearchFailed:
  205.       DoEditDialog := MessageBox('Search string not found.',
  206.         nil, mfError + mfOkButton);
  207.     edReplace:
  208.       DoEditDialog := Application^.ExecuteDialog(CreateReplaceDialog, Info);
  209.     edReplacePrompt:
  210.       begin
  211.         { Avoid placing the dialog on the same line as the cursor }
  212.         R.Assign(0, 1, 40, 8);
  213.         R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  214.         Desktop^.MakeGlobal(R.B, T);
  215.         Inc(T.Y);
  216.         if TPoint(Info).Y <= T.Y then
  217.           R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  218.         DoEditDialog := MessageBoxRect(R, 'Replace this occurence?',
  219.           nil, mfYesNoCancel + mfInformation);
  220.       end;
  221.   end;
  222. end;
  223.  
  224. { TTVDemo }
  225. constructor TTVDemo.Init;
  226. var
  227.   R: TRect;
  228.   I: Integer;
  229.   FileName: PathStr;
  230. begin
  231.   BGIPath:='';
  232.   MaxHeapSize := HeapSize;
  233.   inherited Init;
  234.   RegisterObjects;
  235.   RegisterViews;
  236.   RegisterMenus;
  237.   RegisterDialogs;
  238.   RegisterApp;
  239.   RegisterHelpFile;
  240.   RegisterPuzzle;
  241.   RegisterCalendar;
  242.   RegisterAsciiTab;
  243.   RegisterCalc;
  244.   RegisterEditors;
  245.   RegisterStyx;  { ** TVGRAPH ** }
  246.  
  247.   { Initialize demo gadgets }
  248.  
  249.   GetExtent(R);
  250.   R.A.X := R.B.X - 9; R.B.Y := R.A.Y + 1;
  251.   Clock := New(PClockView, Init(R));
  252.   Insert(Clock);
  253.  
  254.   GetExtent(R);
  255.   Dec(R.B.X);
  256.   R.A.X := R.B.X - 9; R.A.Y := R.B.Y - 1;
  257.   Heap := New(PHeapView, Init(R));
  258.   Insert(Heap);
  259.  
  260.   DisableCommands([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
  261.     cmUndo, cmFind, cmReplace, cmSearchAgain, cmCloseAll]);
  262.   EditorDialog := DoEditDialog;
  263.   ClipWindow := OpenEditor('', False);
  264.   if ClipWindow <> nil then
  265.   begin
  266.     Clipboard := ClipWindow^.Editor;
  267.     Clipboard^.CanUndo := False;
  268.   end;
  269.  
  270.   for I := 1 to ParamCount do
  271.   begin
  272.     FileName := ParamStr(I);
  273.     if FileName[Length(FileName)] = '\' then
  274.       FileName := FileName + '*.*';
  275.     if (Pos('?', FileName) = 0) and (Pos('*', FileName) = 0) then
  276.       OpenEditor(FExpand(FileName), True)
  277.     else FileOpen(FileName);
  278.   end;
  279. end;
  280.  
  281. function TTVDemo.OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  282. var
  283.   P: PView;
  284.   R: TRect;
  285. begin
  286.   DeskTop^.GetExtent(R);
  287.   P := Application^.ValidView(New(PEditWindow,
  288.     Init(R, FileName, wnNoNumber)));
  289.   if not Visible then P^.Hide;
  290.   DeskTop^.Insert(P);
  291.   OpenEditor := PEditWindow(P);
  292. end;
  293.  
  294. procedure TTVDemo.FileOpen(WildCard: PathStr);
  295. var
  296.   FileName: FNameStr;
  297. begin
  298.   FileName := '*.*';
  299.   if ExecuteDialog(New(PFileDialog, Init(WildCard, 'Open a file',
  300.     '~N~ame', fdOpenButton + fdHelpButton, 100)), @FileName) <> cmCancel then
  301.     OpenEditor(FileName, True);
  302. end;
  303.  
  304. procedure TTVDemo.GetEvent(var Event: TEvent);
  305. var
  306.   W: PWindow;
  307.   HFile: PHelpFile;
  308.   HelpStrm: PDosStream;
  309. const
  310.   HelpInUse: Boolean = False;
  311. begin
  312.   inherited GetEvent(Event);
  313.   case Event.What of
  314.     evCommand:
  315.       if (Event.Command = cmHelp) and not HelpInUse then
  316.       begin
  317.         HelpInUse := True;
  318.         HelpStrm := New(PDosStream, Init(CalcHelpName, stOpenRead));
  319.         HFile := New(PHelpFile, Init(HelpStrm));
  320.         if HelpStrm^.Status <> stOk then
  321.         begin
  322.           MessageBox('Could not open help file.', nil, mfError + mfOkButton);
  323.           Dispose(HFile, Done);
  324.         end
  325.         else
  326.         begin
  327.           W := New(PHelpWindow,Init(HFile, GetHelpCtx));
  328.           if ValidView(W) <> nil then
  329.           begin
  330.             ExecView(W);
  331.             Dispose(W, Done);
  332.           end;
  333.           ClearEvent(Event);
  334.         end;
  335.         HelpInUse := False;
  336.       end;
  337.     evMouseDown:
  338.       if Event.Buttons <> 1 then Event.What := evNothing;
  339.   end;
  340. end;
  341.  
  342. function TTVDemo.GetPalette: PPalette;
  343. const
  344.   CNewColor = CAppColor + CHelpColor;
  345.   CNewBlackWhite = CAppBlackWhite + CHelpBlackWhite;
  346.   CNewMonochrome = CAppMonochrome + CHelpMonochrome;
  347.   P: array[apColor..apMonochrome] of string[Length(CNewColor)] =
  348.     (CNewColor, CNewBlackWhite, CNewMonochrome);
  349. begin
  350.   GetPalette := @P[AppPalette];
  351. end;
  352.  
  353. procedure TTVDemo.HandleEvent(var Event: TEvent);
  354.  
  355. procedure ChangeDir;
  356. var
  357.   D: PChDirDialog;
  358. begin
  359.   D := New(PChDirDialog, Init(cdNormal + cdHelpButton, 101));
  360.   D^.HelpCtx := hcFCChDirDBox;
  361.   ExecuteDialog(D, nil);
  362. end;
  363.  
  364. procedure Puzzle;
  365. var
  366.   P: PPuzzleWindow;
  367. begin
  368.   P := New(PPuzzleWindow, Init);
  369.   P^.HelpCtx := hcPuzzle;
  370.   InsertWindow(P);
  371. end;
  372.  
  373. procedure Calendar;
  374. var
  375.   P: PCalendarWindow;
  376. begin
  377.   P := New(PCalendarWindow, Init);
  378.   P^.HelpCtx := hcCalendar;
  379.   InsertWindow(P);
  380. end;
  381.  
  382. procedure About;
  383. var
  384.   D: PDialog;
  385.   Control: PView;
  386.   R: TRect;
  387. begin
  388.   R.Assign(0, 0, 40, 11);
  389.   D := New(PDialog, Init(R, 'About'));
  390.   with D^ do
  391.   begin
  392.     Options := Options or ofCentered;
  393.  
  394.     R.Grow(-1, -1);
  395.     Dec(R.B.Y, 3);
  396.     Insert(New(PStaticText, Init(R,
  397.       #13 +
  398.       ^C'Turbo Vision Demo'#13 +
  399.       #13 +
  400.       ^C'Copyright (c) 1992'#13 +
  401.       #13 +
  402.       ^C'Borland International')));
  403.  
  404.     R.Assign(15, 8, 25, 10);
  405.     Insert(New(PButton, Init(R, 'O~K', cmOk, bfDefault)));
  406.   end;
  407.   if ValidView(D) <> nil then
  408.   begin
  409.     Desktop^.ExecView(D);
  410.     Dispose(D, Done);
  411.   end;
  412. end;
  413.  
  414. procedure AsciiTab;
  415. var
  416.   P: PAsciiChart;
  417. begin
  418.   P := New(PAsciiChart, Init);
  419.   P^.HelpCtx := hcAsciiTable;
  420.   InsertWindow(P);
  421. end;
  422.  
  423. procedure OpenStyx;                      { ** TVGRAPH ** }
  424. var                                      { ** TVGRAPH ** }
  425.   P: PStyxDemo;                          { ** TVGRAPH ** }
  426. begin                                    { ** TVGRAPH ** }
  427.   P := New(PStyxDemo, Init);             { ** TVGRAPH ** }
  428.   P^.HelpCtx := hcNoContext;             { ** TVGRAPH ** }
  429.   Desktop^.Insert(ValidView(P));         { ** TVGRAPH ** }
  430. end;                                     { ** TVGRAPH ** }
  431.  
  432. procedure Calculator;
  433. var
  434.   P: PCalculator;
  435. begin
  436.   P := New(PCalculator, Init);
  437.   P^.HelpCtx := hcCalculator;
  438.   InsertWindow(P);
  439. end;
  440.  
  441. procedure Colors;
  442. var
  443.   D: PColorDialog;
  444. begin
  445.   D := New(PColorDialog, Init('',
  446.     ColorGroup('Desktop',       DesktopColorItems(nil),
  447.     ColorGroup('Menus',         MenuColorItems(nil),
  448.     ColorGroup('Dialogs/Calc',  DialogColorItems(dpGrayDialog, nil),
  449.     ColorGroup('Editor/Puzzle', WindowColorItems(wpBlueWindow, nil),
  450.     ColorGroup('Ascii table',   WindowColorItems(wpGrayWindow, nil),
  451.     ColorGroup('Calendar',
  452.       WindowColorItems(wpCyanWindow,
  453.       ColorItem('Current day',       22, nil)),
  454.       nil))))))));
  455.  
  456.   D^.HelpCtx := hcOCColorsDBox;
  457.  
  458.   if ExecuteDialog(D, Application^.GetPalette) <> cmCancel then
  459.   begin
  460.     DoneMemory;    { Dispose all group buffers }
  461.     ReDraw;        { Redraw application with new palette }
  462.   end;
  463. end;
  464.  
  465. procedure Mouse;
  466. var
  467.   D: PDialog;
  468. begin
  469.   D := New(PMouseDialog, Init);
  470.   D^.HelpCtx := hcOMMouseDBox;
  471.   ExecuteDialog(D, @MouseReverse);
  472. end;
  473.  
  474. procedure RetrieveDesktop;
  475. var
  476.   S: PStream;
  477.   Signature: string[SignatureLen];
  478. begin
  479.   S := New(PBufStream, Init('TVDEMO.DSK', stOpenRead, 1024));
  480.   if LowMemory then OutOfMemory
  481.   else if S^.Status <> stOk then
  482.     MessageBox('Could not open desktop file', nil, mfOkButton + mfError)
  483.   else
  484.   begin
  485.     Signature[0] := Char(SignatureLen);
  486.     S^.Read(Signature[1], SignatureLen);
  487.     if Signature = DSKSignature then
  488.     begin
  489.       LoadDesktop(S^);
  490.       LoadIndexes(S^);
  491.       LoadHistory(S^);
  492.       if S^.Status <> stOk then
  493.         MessageBox('Error reading desktop file', nil, mfOkButton + mfError);
  494.     end
  495.     else
  496.       MessageBox('Error: Invalid Desktop file.', nil, mfOkButton + mfError);
  497.   end;
  498.   Dispose(S, Done);
  499. end;
  500.  
  501. procedure SaveDesktop;
  502. var
  503.   S: PStream;
  504.   F: File;
  505. begin
  506.   S := New(PBufStream, Init('TVDEMO.DSK', stCreate, 1024));
  507.   if not LowMemory and (S^.Status = stOk) then
  508.   begin
  509.     S^.Write(DSKSignature[1], SignatureLen);
  510.     StoreDesktop(S^);
  511.     StoreIndexes(S^);
  512.     StoreHistory(S^);
  513.     if S^.Status <> stOk then
  514.     begin
  515.       MessageBox('Could not create TVDEMO.DSK.', nil, mfOkButton + mfError);
  516.       {$I-}
  517.       Dispose(S, Done);
  518.       Assign(F, 'TVDEMO.DSK');
  519.       Erase(F);
  520.       Exit;
  521.     end;
  522.   end;
  523.   Dispose(S, Done);
  524. end;
  525.  
  526. procedure FileNew;
  527. begin
  528.   OpenEditor('', True);
  529. end;
  530.  
  531. procedure ShowClip;
  532. begin
  533.   ClipWindow^.Select;
  534.   ClipWindow^.Show;
  535. end;
  536.  
  537. begin
  538.   inherited HandleEvent(Event);
  539.   case Event.What of
  540.     evCommand:
  541.       begin
  542.         case Event.Command of
  543.           cmOpen: FileOpen('*.*');
  544.           cmNew: FileNew;
  545.           cmShowClip: ShowClip;
  546.           cmChangeDir: ChangeDir;
  547.           cmAbout: About;
  548.           cmPuzzle: Puzzle;
  549.           cmCalendar: Calendar;
  550.           cmAsciiTab: AsciiTab;
  551.           cmCalculator: Calculator;
  552.           cmColors: Colors;
  553.           cmMouse: Mouse;
  554.           cmSaveDesktop: SaveDesktop;
  555.           cmRetrieveDesktop: RetrieveDesktop;
  556.           cmStyx: OpenStyx;                      { ** TVGRAPH ** }
  557.         else
  558.           Exit;
  559.         end;
  560.         ClearEvent(Event);
  561.       end;
  562.   end;
  563. end;
  564.  
  565. procedure TTVDemo.Idle;
  566.  
  567. function IsTileable(P: PView): Boolean; far;
  568. begin
  569.   IsTileable := (P^.Options and ofTileable <> 0) and
  570.     (P^.State and sfVisible <> 0);
  571. end;
  572.  
  573. procedure DoProdStyx(P: PView); far;                   { ** TVGRAPH ** }
  574. begin                                                  { ** TVGRAPH ** }
  575.   Message(P, evCommand ,cmTVGraphProd, nil);           { ** TVGRAPH ** }
  576. end;                                                   { ** TVGRAPH ** }
  577.  
  578. begin
  579.   inherited Idle;
  580.   Clock^.Update;
  581.   Heap^.Update;
  582.  
  583.   Desktop^.ForEach(@DoProdStyx);                    { ** TVGRAPH ** }
  584.  
  585.   if Desktop^.FirstThat(@IsTileable) <> nil then
  586.     EnableCommands([cmTile, cmCascade])
  587.   else
  588.     DisableCommands([cmTile, cmCascade]);
  589. end;
  590.  
  591. procedure TTVDemo.InitMenuBar;
  592. var
  593.   R: TRect;
  594. begin
  595.   GetExtent(R);
  596.   R.B.Y := R.A.Y+1;
  597.   MenuBar := New(PMenuBar, Init(R, NewMenu(
  598.     NewSubMenu('~'#240'~', hcSystem, NewMenu(
  599.       NewItem('~A~bout', '', kbNoKey, cmAbout, hcSAbout,
  600.       NewLine(
  601.       NewItem('~P~uzzle', '', kbNoKey, cmPuzzle, hcSPuzzle,
  602.       NewItem('Ca~l~endar', '', kbNoKey, cmCalendar, hcSCalendar,
  603.       NewItem('Ascii ~t~able', '', kbNoKey, cmAsciiTab, hcSAsciiTable,
  604.       NewItem('~S~tyx', '', kbNoKey, cmStyx, hcNoContext,      { ** TVGRAPH ** }
  605.       NewItem('~C~alculator', '', kbNoKey, cmCalculator, hcCalculator, nil)))))))),
  606.     NewSubMenu('~F~ile', hcFile, NewMenu(
  607.       StdFileMenuItems(nil)),
  608.     NewSubMenu('~E~dit', hcEdit, NewMenu(
  609.       StdEditMenuItems(
  610.       NewLine(
  611.       NewItem('~S~how clipboard', '', kbNoKey, cmShowClip, hcShowClip,
  612.       nil)))),
  613.     NewSubMenu('~S~earch', hcSearch, NewMenu(
  614.       NewItem('~F~ind...', '', kbNoKey, cmFind, hcFind,
  615.       NewItem('~R~eplace...', '', kbNoKey, cmReplace, hcReplace,
  616.       NewItem('~S~earch again', '', kbNoKey, cmSearchAgain, hcSearchAgain,
  617.       nil)))),
  618.     NewSubMenu('~W~indow', hcWindows, NewMenu(
  619.       StdWindowMenuItems(nil)),
  620.     NewSubMenu('~O~ptions', hcOptions, NewMenu(
  621.       NewItem('~M~ouse...', '', kbNoKey, cmMouse, hcOMouse,
  622.       NewItem('~C~olors...', '', kbNoKey, cmColors, hcOColors,
  623.       NewLine(
  624.       NewItem('~S~ave desktop', '', kbNoKey, cmSaveDesktop, hcOSaveDesktop,
  625.       NewItem('~R~etrieve desktop', '', kbNoKey, cmRetrieveDesktop, hcORestoreDesktop, nil)))))),
  626.       nil)))))))));
  627. end;
  628.  
  629. procedure TTVDemo.InitStatusLine;
  630. var
  631.   R: TRect;
  632. begin
  633.   GetExtent(R);
  634.   R.A.Y := R.B.Y - 1;
  635.   StatusLine := New(PStatusLine, Init(R,
  636.     NewStatusDef(0, $FFFF,
  637.       NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
  638.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  639.       NewStatusKey('~F3~ Open', kbF3, cmOpen,
  640.       NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose,
  641.       NewStatusKey('~F5~ Zoom', kbF5, cmZoom,
  642.       NewStatusKey('', kbF10, cmMenu,
  643.       NewStatusKey('', kbCtrlF5, cmResize,
  644.       nil))))))),
  645.     nil)));
  646. end;
  647.  
  648. procedure TTVDemo.OutOfMemory;
  649. begin
  650.   MessageBox('Not enough memory available to complete operation.',
  651.     nil, mfError + mfOkButton);
  652. end;
  653.  
  654. { Since the safety pool is only large enough to guarantee that allocating
  655.   a window will not run out of memory, loading the entire desktop without
  656.   checking LowMemory could cause a heap error.  This means that each
  657.   window should be read individually, instead of using Desktop's Load.
  658. }
  659.  
  660. procedure TTVDemo.LoadDesktop(var S: TStream);
  661. var
  662.   P: PView;
  663.   Pal: PString;
  664.  
  665. procedure CloseView(P: PView); far;
  666. begin
  667.   Message(P, evCommand, cmClose, nil);
  668. end;
  669.  
  670. begin
  671.   if Desktop^.Valid(cmClose) then
  672.   begin
  673.     Desktop^.ForEach(@CloseView); { Clear the desktop }
  674.     repeat
  675.       P := PView(S.Get);
  676.       Desktop^.InsertBefore(ValidView(P), Desktop^.Last);
  677.     until P = nil;
  678.     Pal := S.ReadStr;
  679.     if Pal <> nil then
  680.     begin
  681.       Application^.GetPalette^ := Pal^;
  682.       DoneMemory;
  683.       Application^.ReDraw;
  684.       DisposeStr(Pal);
  685.     end;
  686.   end;
  687. end;
  688.  
  689. procedure TTVDemo.StoreDesktop(var S: TStream);
  690. var
  691.   Pal: PString;
  692.  
  693. procedure WriteView(P: PView); far;
  694. begin
  695.   if P <> Desktop^.Last then S.Put(P);
  696. end;
  697.  
  698. begin
  699.   Desktop^.ForEach(@WriteView);
  700.   S.Put(nil);
  701.   Pal := @Application^.GetPalette^;
  702.   S.WriteStr(Pal);
  703. end;
  704.  
  705.  
  706. var
  707.   Demo: TTVDemo;
  708.  
  709. begin
  710.   Demo.Init;
  711.   Demo.Run;
  712.   Demo.Done;
  713. end.
  714.